#pragma once
#include <iostream>
#include <functional>
#include <vector>
#include <pthread.h>
#include <unordered_map>
#include "Sock.hpp"

using func_t = std::function<void(int)>;

class TcpServer;
class ThreadData
{
public:
    ThreadData(int sock,TcpServer* server)
        :_sock(sock),_server(server)
    {}
    ~ThreadData()
    {}
public:
    int _sock;
    TcpServer *_server;
};

class TcpServer
{
private:
    static void *ThreadRoutine(void *args)
    {
        pthread_detach(pthread_self());
        ThreadData* td= static_cast<ThreadData*>(args);
        td->_server->Excute(td->_sock);
        close(td->_sock);
        // delete td;
        return nullptr;
    }

public:
    TcpServer(const uint16_t &port, const std::string &ip = "0.0.0.0")
    {
        _listensock = _sock.Socket();
        _sock.Bind(_listensock, port, ip);
        _sock.Listen(_listensock);
    }
    void BindService(func_t func)
    {
        _func.push_back(func);
    }
    void Excute(int sock)
    {
        for (auto &f : _func)
        {
            f(sock);
        }
    }
    void Start()
    {
        for (;;)
        {
            std::string clientip;
            uint16_t clientport;
            int servicesock = _sock.Accept(_listensock, &clientip, &clientport);
            if (servicesock == -1)
                continue;
            logMessage(NORMAL, "creat link success servicesock:%d", servicesock);
            pthread_t tid;
            ThreadData* td = new ThreadData(servicesock,this);
            pthread_create(&tid, nullptr, ThreadRoutine, (void*)td);
        }
    }
    ~TcpServer()
    {
        if (_listensock >= 0)
            close(_listensock);
    }

private:
    int _listensock;
    Sock _sock;
    std::vector<func_t> _func;
};
